home *** CD-ROM | disk | FTP | other *** search
/ Australian Personal Computer 2002 November / CD 1 / APC0211D1.ISO / workshop / prog / files / ActivePerl-5.6.1.633-MSWin32.msi / _efb1b312a50a4c430be79d686e794252 < prev    next >
Encoding:
Text File  |  2001-09-04  |  17.3 KB  |  694 lines

  1. /* vdir.h
  2.  *
  3.  * (c) 1999 Microsoft Corporation. All rights reserved. 
  4.  * Portions (c) 1999 ActiveState Tool Corp, http://www.ActiveState.com/
  5.  *
  6.  *    You may distribute under the terms of either the GNU General Public
  7.  *    License or the Artistic License, as specified in the README file.
  8.  */
  9.  
  10. #ifndef ___VDir_H___
  11. #define ___VDir_H___
  12.  
  13. /*
  14.  * Allow one slot for each possible drive letter
  15.  * and one additional slot for a UNC name
  16.  */
  17. const int driveCount = ('Z'-'A')+1+1;
  18.  
  19. class VDir
  20. {
  21. public:
  22.     VDir(int bManageDir = 1);
  23.     ~VDir() {};
  24.  
  25.     void Init(VDir* pDir, VMem *pMem);
  26.     void SetDefaultA(char const *pDefault);
  27.     void SetDefaultW(WCHAR const *pDefault);
  28.     char* MapPathA(const char *pInName);
  29.     WCHAR* MapPathW(const WCHAR *pInName);
  30.     int SetCurrentDirectoryA(char *lpBuffer);
  31.     int SetCurrentDirectoryW(WCHAR *lpBuffer);
  32.     inline int GetDefault(void) { return nDefault; };
  33.  
  34.     inline char* GetCurrentDirectoryA(int dwBufSize, char *lpBuffer)
  35.     {
  36.     char* ptr = dirTableA[nDefault];
  37.     while (dwBufSize--)
  38.     {
  39.         if ((*lpBuffer++ = *ptr++) == '\0')
  40.         break;
  41.     }
  42.     return lpBuffer;
  43.     };
  44.     inline WCHAR* GetCurrentDirectoryW(int dwBufSize, WCHAR *lpBuffer)
  45.     {
  46.     WCHAR* ptr = dirTableW[nDefault];
  47.     while (dwBufSize--)
  48.     {
  49.         if ((*lpBuffer++ = *ptr++) == '\0')
  50.         break;
  51.     }
  52.     return lpBuffer;
  53.     };
  54.  
  55.  
  56.     DWORD CalculateEnvironmentSpace(void);
  57.     LPSTR BuildEnvironmentSpace(LPSTR lpStr);
  58.  
  59. protected:
  60.     int SetDirA(char const *pPath, int index);
  61.     void FromEnvA(char *pEnv, int index);
  62.     inline const char *GetDefaultDirA(void)
  63.     {
  64.     return dirTableA[nDefault];
  65.     };
  66.  
  67.     inline void SetDefaultDirA(char const *pPath, int index)
  68.     {
  69.     SetDirA(pPath, index);
  70.     nDefault = index;
  71.     };
  72.     int SetDirW(WCHAR const *pPath, int index);
  73.     inline const WCHAR *GetDefaultDirW(void)
  74.     {
  75.     return dirTableW[nDefault];
  76.     };
  77.  
  78.     inline void SetDefaultDirW(WCHAR const *pPath, int index)
  79.     {
  80.     SetDirW(pPath, index);
  81.     nDefault = index;
  82.     };
  83.     inline const char *GetDirA(int index)
  84.     {
  85.     char *ptr = dirTableA[index];
  86.     if (!ptr) {
  87.         /* simulate the existance of this drive */
  88.         ptr = szLocalBufferA;
  89.         ptr[0] = 'A' + index;
  90.         ptr[1] = ':';
  91.         ptr[2] = '\\';
  92.         ptr[3] = 0;
  93.     }
  94.     return ptr;
  95.     };
  96.     inline const WCHAR *GetDirW(int index)
  97.     {
  98.     WCHAR *ptr = dirTableW[index];
  99.     if (!ptr) {
  100.         /* simulate the existance of this drive */
  101.         ptr = szLocalBufferW;
  102.         ptr[0] = 'A' + index;
  103.         ptr[1] = ':';
  104.         ptr[2] = '\\';
  105.         ptr[3] = 0;
  106.     }
  107.     return ptr;
  108.     };
  109.  
  110.     inline int DriveIndex(char chr)
  111.     {
  112.     if (chr == '\\' || chr == '/')
  113.         return ('Z'-'A')+1;
  114.     return (chr | 0x20)-'a';
  115.     };
  116.  
  117.     VMem *pMem;
  118.     int nDefault, bManageDirectory;
  119.     char *dirTableA[driveCount];
  120.     char szLocalBufferA[MAX_PATH+1];
  121.     WCHAR *dirTableW[driveCount];
  122.     WCHAR szLocalBufferW[MAX_PATH+1];
  123. };
  124.  
  125.  
  126. VDir::VDir(int bManageDir /* = 1 */)
  127. {
  128.     nDefault = 0;
  129.     bManageDirectory = bManageDir;
  130.     memset(dirTableA, 0, sizeof(dirTableA));
  131.     memset(dirTableW, 0, sizeof(dirTableW));
  132. }
  133.  
  134. void VDir::Init(VDir* pDir, VMem *p)
  135. {
  136.     int index;
  137.     DWORD driveBits;
  138.     int nSave;
  139.     char szBuffer[MAX_PATH*driveCount];
  140.  
  141.     pMem = p;
  142.     if (pDir) {
  143.     for (index = 0; index < driveCount; ++index) {
  144.         SetDirW(pDir->GetDirW(index), index);
  145.     }
  146.     nDefault = pDir->GetDefault();
  147.     }
  148.     else {
  149.     nSave = bManageDirectory;
  150.     bManageDirectory = 0;
  151.     driveBits = GetLogicalDrives();
  152.     if (GetLogicalDriveStrings(sizeof(szBuffer), szBuffer)) {
  153.         char* pEnv = GetEnvironmentStrings();
  154.         char* ptr = szBuffer;
  155.         for (index = 0; index < driveCount; ++index) {
  156.         if (driveBits & (1<<index)) {
  157.             ptr += SetDirA(ptr, index) + 1;
  158.             FromEnvA(pEnv, index);
  159.         }
  160.         }
  161.         FreeEnvironmentStrings(pEnv);
  162.     }
  163.     SetDefaultA(".");
  164.     bManageDirectory = nSave;
  165.     }
  166. }
  167.  
  168. int VDir::SetDirA(char const *pPath, int index)
  169. {
  170.     char chr, *ptr;
  171.     int length = 0;
  172.     WCHAR wBuffer[MAX_PATH+1];
  173.     if (index < driveCount && pPath != NULL) {
  174.     length = strlen(pPath);
  175.     pMem->Free(dirTableA[index]);
  176.     ptr = dirTableA[index] = (char*)pMem->Malloc(length+2);
  177.     if (ptr != NULL) {
  178.         strcpy(ptr, pPath);
  179.         ptr += length-1;
  180.         chr = *ptr++;
  181.         if (chr != '\\' && chr != '/') {
  182.         *ptr++ = '\\';
  183.         *ptr = '\0';
  184.         }
  185.         MultiByteToWideChar(CP_ACP, 0, dirTableA[index], -1,
  186.             wBuffer, (sizeof(wBuffer)/sizeof(WCHAR)));
  187.         length = wcslen(wBuffer);
  188.         pMem->Free(dirTableW[index]);
  189.         dirTableW[index] = (WCHAR*)pMem->Malloc((length+1)*2);
  190.         if (dirTableW[index] != NULL) {
  191.         wcscpy(dirTableW[index], wBuffer);
  192.         }
  193.     }
  194.     }
  195.  
  196.     if(bManageDirectory)
  197.     ::SetCurrentDirectoryA(pPath);
  198.  
  199.     return length;
  200. }
  201.  
  202. void VDir::FromEnvA(char *pEnv, int index)
  203. {   /* gets the directory for index from the environment variable. */
  204.     while (*pEnv != '\0') {
  205.     if ((pEnv[0] == '=') && (DriveIndex(pEnv[1]) == index)) {
  206.         SetDirA(&pEnv[4], index);
  207.         break;
  208.     }
  209.     else
  210.         pEnv += strlen(pEnv)+1;
  211.     }
  212. }
  213.  
  214. void VDir::SetDefaultA(char const *pDefault)
  215. {
  216.     char szBuffer[MAX_PATH+1];
  217.     char *pPtr;
  218.  
  219.     if (GetFullPathNameA(pDefault, sizeof(szBuffer), szBuffer, &pPtr)) {
  220.         if (*pDefault != '.' && pPtr != NULL)
  221.         *pPtr = '\0';
  222.  
  223.     SetDefaultDirA(szBuffer, DriveIndex(szBuffer[0]));
  224.     }
  225. }
  226.  
  227. int VDir::SetDirW(WCHAR const *pPath, int index)
  228. {
  229.     WCHAR chr, *ptr;
  230.     char szBuffer[MAX_PATH+1];
  231.     int length = 0;
  232.     if (index < driveCount && pPath != NULL) {
  233.     length = wcslen(pPath);
  234.     pMem->Free(dirTableW[index]);
  235.     ptr = dirTableW[index] = (WCHAR*)pMem->Malloc((length+2)*2);
  236.     if (ptr != NULL) {
  237.         wcscpy(ptr, pPath);
  238.         ptr += length-1;
  239.         chr = *ptr++;
  240.         if (chr != '\\' && chr != '/') {
  241.         *ptr++ = '\\';
  242.         *ptr = '\0';
  243.         }
  244.         WideCharToMultiByte(CP_ACP, 0, dirTableW[index], -1, szBuffer, sizeof(szBuffer), NULL, NULL);
  245.         length = strlen(szBuffer);
  246.         pMem->Free(dirTableA[index]);
  247.         dirTableA[index] = (char*)pMem->Malloc(length+1);
  248.         if (dirTableA[index] != NULL) {
  249.         strcpy(dirTableA[index], szBuffer);
  250.         }
  251.     }
  252.     }
  253.  
  254.     if(bManageDirectory)
  255.     ::SetCurrentDirectoryW(pPath);
  256.  
  257.     return length;
  258. }
  259.  
  260. void VDir::SetDefaultW(WCHAR const *pDefault)
  261. {
  262.     WCHAR szBuffer[MAX_PATH+1];
  263.     WCHAR *pPtr;
  264.  
  265.     if (GetFullPathNameW(pDefault, (sizeof(szBuffer)/sizeof(WCHAR)), szBuffer, &pPtr)) {
  266.         if (*pDefault != '.' && pPtr != NULL)
  267.         *pPtr = '\0';
  268.  
  269.     SetDefaultDirW(szBuffer, DriveIndex((char)szBuffer[0]));
  270.     }
  271. }
  272.  
  273. inline BOOL IsPathSep(char ch)
  274. {
  275.     return (ch == '\\' || ch == '/');
  276. }
  277.  
  278. inline void DoGetFullPathNameA(char* lpBuffer, DWORD dwSize, char* Dest)
  279. {
  280.     char *pPtr;
  281.  
  282.     /*
  283.      * On WinNT GetFullPathName does not fail, (or at least always
  284.      * succeeds when the drive is valid) WinNT does set *Dest to Nullch
  285.      * On Win98 GetFullPathName will set last error if it fails, but
  286.      * does not touch *Dest
  287.      */
  288.     *Dest = '\0';
  289.     GetFullPathNameA(lpBuffer, dwSize, Dest, &pPtr);
  290. }
  291.  
  292. inline bool IsSpecialFileName(const char* pName)
  293. {
  294.     /* specical file names are devices that the system can open
  295.      * these include AUX, CON, NUL, PRN, COMx, LPTx, CLOCK$, CONIN$, CONOUT$
  296.      * (x is a single digit, and names are case-insensitive)
  297.      */
  298.     char ch = (pName[0] & ~0x20);
  299.     switch (ch)
  300.     {
  301.     case 'A': /* AUX */
  302.         if (((pName[1] & ~0x20) == 'U')
  303.         && ((pName[2] & ~0x20) == 'X')
  304.         && !pName[3])
  305.             return true;
  306.         break;
  307.     case 'C': /* CLOCK$, COMx,  CON, CONIN$ CONOUT$ */
  308.         ch = (pName[1] & ~0x20);
  309.         switch (ch)
  310.         {
  311.         case 'L': /* CLOCK$ */
  312.             if (((pName[2] & ~0x20) == 'O')
  313.             && ((pName[3] & ~0x20) == 'C')
  314.             && ((pName[4] & ~0x20) == 'K')
  315.             && (pName[5] == '$')
  316.             && !pName[6])
  317.                 return true;
  318.             break;
  319.         case 'O': /* COMx,  CON, CONIN$ CONOUT$ */
  320.             if ((pName[2] & ~0x20) == 'M') {
  321.             if ((pName[3] >= '1') && (pName[3] <= '9')
  322.                 && !pName[4])
  323.                 return true;
  324.             }
  325.             else if ((pName[2] & ~0x20) == 'N') {
  326.             if (!pName[3])
  327.                 return true;
  328.             else if ((pName[3] & ~0x20) == 'I') {
  329.                 if (((pName[4] & ~0x20) == 'N')
  330.                 && (pName[5] == '$')
  331.                 && !pName[6])
  332.                 return true;
  333.             }
  334.             else if ((pName[3] & ~0x20) == 'O') {
  335.                 if (((pName[4] & ~0x20) == 'U')
  336.                 && ((pName[5] & ~0x20) == 'T')
  337.                 && (pName[6] == '$')
  338.                 && !pName[7])
  339.                 return true;
  340.             }
  341.             }
  342.             break;
  343.         }
  344.         break;
  345.     case 'L': /* LPTx */
  346.         if (((pName[1] & ~0x20) == 'U')
  347.         && ((pName[2] & ~0x20) == 'X')
  348.         && (pName[3] >= '1') && (pName[3] <= '9')
  349.         && !pName[4])
  350.             return true;
  351.         break;
  352.     case 'N': /* NUL */
  353.         if (((pName[1] & ~0x20) == 'U')
  354.         && ((pName[2] & ~0x20) == 'L')
  355.         && !pName[3])
  356.             return true;
  357.         break;
  358.     case 'P': /* PRN */
  359.         if (((pName[1] & ~0x20) == 'R')
  360.         && ((pName[2] & ~0x20) == 'N')
  361.         && !pName[3])
  362.             return true;
  363.         break;
  364.     }
  365.     return false;
  366. }
  367.  
  368. char *VDir::MapPathA(const char *pInName)
  369. {   /*
  370.      * possiblities -- relative path or absolute path with or without drive letter
  371.      * OR UNC name
  372.      */
  373.     char szBuffer[(MAX_PATH+1)*2];
  374.     char szlBuf[MAX_PATH+1];
  375.     int length = strlen(pInName);
  376.  
  377.     if (!length)
  378.     return (char*)pInName;
  379.  
  380.     if (length > MAX_PATH) {
  381.     strncpy(szlBuf, pInName, MAX_PATH);
  382.     if (IsPathSep(pInName[0]) && !IsPathSep(pInName[1])) {   
  383.         /* absolute path - reduce length by 2 for drive specifier */
  384.         szlBuf[MAX_PATH-2] = '\0';
  385.     }
  386.     else
  387.         szlBuf[MAX_PATH] = '\0';
  388.     pInName = szlBuf;
  389.     }
  390.     /* strlen(pInName) is now <= MAX_PATH */
  391.  
  392.     if (pInName[1] == ':') {
  393.     /* has drive letter */
  394.     if (IsPathSep(pInName[2])) {
  395.         /* absolute with drive letter */
  396.         strcpy(szLocalBufferA, pInName);
  397.     }
  398.     else {
  399.         /* relative path with drive letter */
  400.         strcpy(szBuffer, GetDirA(DriveIndex(*pInName)));
  401.         strcat(szBuffer, &pInName[2]);
  402.         if(strlen(szBuffer) > MAX_PATH)
  403.         szBuffer[MAX_PATH] = '\0';
  404.  
  405.         DoGetFullPathNameA(szBuffer, sizeof(szLocalBufferA), szLocalBufferA);
  406.     }
  407.     }
  408.     else {
  409.     /* no drive letter */
  410.     if (IsPathSep(pInName[1]) && IsPathSep(pInName[0])) {
  411.         /* UNC name */
  412.         strcpy(szLocalBufferA, pInName);
  413.     }
  414.     else {
  415.         strcpy(szBuffer, GetDefaultDirA());
  416.         if (IsPathSep(pInName[0])) {
  417.         /* absolute path */
  418.         szLocalBufferA[0] = szBuffer[0];
  419.         szLocalBufferA[1] = szBuffer[1];
  420.         strcpy(&szLocalBufferA[2], pInName);
  421.         }
  422.         else {
  423.         /* relative path */
  424.         if (IsSpecialFileName(pInName)) {
  425.             return (char*)pInName;
  426.         }
  427.         else {
  428.             strcat(szBuffer, pInName);
  429.             if (strlen(szBuffer) > MAX_PATH)
  430.             szBuffer[MAX_PATH] = '\0';
  431.  
  432.             DoGetFullPathNameA(szBuffer, sizeof(szLocalBufferA), szLocalBufferA);
  433.         }
  434.         }
  435.     }
  436.     }
  437.  
  438.     return szLocalBufferA;
  439. }
  440.  
  441. int VDir::SetCurrentDirectoryA(char *lpBuffer)
  442. {
  443.     char *pPtr;
  444.     int length, nRet = -1;
  445.  
  446.     pPtr = MapPathA(lpBuffer);
  447.     length = strlen(pPtr);
  448.     if(length > 3 && IsPathSep(pPtr[length-1])) {
  449.     /* don't remove the trailing slash from 'x:\'  */
  450.     pPtr[length-1] = '\0';
  451.     }
  452.  
  453.     DWORD r = GetFileAttributesA(pPtr);
  454.     if ((r != 0xffffffff) && (r & FILE_ATTRIBUTE_DIRECTORY))
  455.     {
  456.     char szBuffer[(MAX_PATH+1)*2];
  457.     DoGetFullPathNameA(pPtr, sizeof(szBuffer), szBuffer);
  458.     SetDefaultDirA(szBuffer, DriveIndex(szBuffer[0]));
  459.     nRet = 0;
  460.     }
  461.  
  462.     return nRet;
  463. }
  464.  
  465. DWORD VDir::CalculateEnvironmentSpace(void)
  466. {   /* the current directory environment strings are stored as '=D:=d:\path' */
  467.     int index;
  468.     DWORD dwSize = 0;
  469.     for (index = 0; index < driveCount; ++index) {
  470.     if (dirTableA[index] != NULL) {
  471.         dwSize += strlen(dirTableA[index]) + 5;  /* add 1 for trailing NULL and 4 for '=D:=' */
  472.     }
  473.     }
  474.     return dwSize;
  475. }
  476.  
  477. LPSTR VDir::BuildEnvironmentSpace(LPSTR lpStr)
  478. {   /* store the current directory environment strings as '=D:=d:\path' */
  479.     int index, length;
  480.     LPSTR lpDirStr;
  481.     for (index = 0; index < driveCount; ++index) {
  482.     lpDirStr = dirTableA[index];
  483.     if (lpDirStr != NULL) {
  484.         lpStr[0] = '=';
  485.         lpStr[1] = lpDirStr[0];
  486.         lpStr[2] = '\0';
  487.         CharUpper(&lpStr[1]);
  488.         lpStr[2] = ':';
  489.         lpStr[3] = '=';
  490.         strcpy(&lpStr[4], lpDirStr);
  491.         length = strlen(lpDirStr);
  492.         lpStr += length + 5; /* add 1 for trailing NULL and 4 for '=D:=' */
  493.         if (length > 3 && IsPathSep(lpStr[-2])) {
  494.         lpStr[-2] = '\0';   /* remove the trailing path separator */
  495.         --lpStr;
  496.         }
  497.     }
  498.     }
  499.     return lpStr;
  500. }
  501.  
  502. inline BOOL IsPathSep(WCHAR ch)
  503. {
  504.     return (ch == '\\' || ch == '/');
  505. }
  506.  
  507. inline void DoGetFullPathNameW(WCHAR* lpBuffer, DWORD dwSize, WCHAR* Dest)
  508. {
  509.     WCHAR *pPtr;
  510.  
  511.     /*
  512.      * On WinNT GetFullPathName does not fail, (or at least always
  513.      * succeeds when the drive is valid) WinNT does set *Dest to Nullch
  514.      * On Win98 GetFullPathName will set last error if it fails, but
  515.      * does not touch *Dest
  516.      */
  517.     *Dest = '\0';
  518.     GetFullPathNameW(lpBuffer, dwSize, Dest, &pPtr);
  519. }
  520.  
  521. inline bool IsSpecialFileName(const WCHAR* pName)
  522. {
  523.     /* specical file names are devices that the system can open
  524.      * these include AUX, CON, NUL, PRN, COMx, LPTx, CLOCK$, CONIN$, CONOUT$
  525.      * (x is a single digit, and names are case-insensitive)
  526.      */
  527.     WCHAR ch = (pName[0] & ~0x20);
  528.     switch (ch)
  529.     {
  530.     case 'A': /* AUX */
  531.         if (((pName[1] & ~0x20) == 'U')
  532.         && ((pName[2] & ~0x20) == 'X')
  533.         && !pName[3])
  534.             return true;
  535.         break;
  536.     case 'C': /* CLOCK$, COMx,  CON, CONIN$ CONOUT$ */
  537.         ch = (pName[1] & ~0x20);
  538.         switch (ch)
  539.         {
  540.         case 'L': /* CLOCK$ */
  541.             if (((pName[2] & ~0x20) == 'O')
  542.             && ((pName[3] & ~0x20) == 'C')
  543.             && ((pName[4] & ~0x20) == 'K')
  544.             && (pName[5] == '$')
  545.             && !pName[6])
  546.                 return true;
  547.             break;
  548.         case 'O': /* COMx,  CON, CONIN$ CONOUT$ */
  549.             if ((pName[2] & ~0x20) == 'M') {
  550.             if ((pName[3] >= '1') && (pName[3] <= '9')
  551.                 && !pName[4])
  552.                 return true;
  553.             }
  554.             else if ((pName[2] & ~0x20) == 'N') {
  555.             if (!pName[3])
  556.                 return true;
  557.             else if ((pName[3] & ~0x20) == 'I') {
  558.                 if (((pName[4] & ~0x20) == 'N')
  559.                 && (pName[5] == '$')
  560.                 && !pName[6])
  561.                 return true;
  562.             }
  563.             else if ((pName[3] & ~0x20) == 'O') {
  564.                 if (((pName[4] & ~0x20) == 'U')
  565.                 && ((pName[5] & ~0x20) == 'T')
  566.                 && (pName[6] == '$')
  567.                 && !pName[7])
  568.                 return true;
  569.             }
  570.             }
  571.             break;
  572.         }
  573.         break;
  574.     case 'L': /* LPTx */
  575.         if (((pName[1] & ~0x20) == 'U')
  576.         && ((pName[2] & ~0x20) == 'X')
  577.         && (pName[3] >= '1') && (pName[3] <= '9')
  578.         && !pName[4])
  579.             return true;
  580.         break;
  581.     case 'N': /* NUL */
  582.         if (((pName[1] & ~0x20) == 'U')
  583.         && ((pName[2] & ~0x20) == 'L')
  584.         && !pName[3])
  585.             return true;
  586.         break;
  587.     case 'P': /* PRN */
  588.         if (((pName[1] & ~0x20) == 'R')
  589.         && ((pName[2] & ~0x20) == 'N')
  590.         && !pName[3])
  591.             return true;
  592.         break;
  593.     }
  594.     return false;
  595. }
  596.  
  597. WCHAR* VDir::MapPathW(const WCHAR *pInName)
  598. {   /*
  599.      * possiblities -- relative path or absolute path with or without drive letter
  600.      * OR UNC name
  601.      */
  602.     WCHAR szBuffer[(MAX_PATH+1)*2];
  603.     WCHAR szlBuf[MAX_PATH+1];
  604.     int length = wcslen(pInName);
  605.  
  606.     if (!length)
  607.     return (WCHAR*)pInName;
  608.  
  609.     if (length > MAX_PATH) {
  610.     wcsncpy(szlBuf, pInName, MAX_PATH);
  611.     if (IsPathSep(pInName[0]) && !IsPathSep(pInName[1])) {   
  612.         /* absolute path - reduce length by 2 for drive specifier */
  613.         szlBuf[MAX_PATH-2] = '\0';
  614.     }
  615.     else
  616.         szlBuf[MAX_PATH] = '\0';
  617.     pInName = szlBuf;
  618.     }
  619.     /* strlen(pInName) is now <= MAX_PATH */
  620.  
  621.     if (pInName[1] == ':') {
  622.     /* has drive letter */
  623.     if (IsPathSep(pInName[2])) {
  624.         /* absolute with drive letter */
  625.         wcscpy(szLocalBufferW, pInName);
  626.     }
  627.     else {
  628.         /* relative path with drive letter */
  629.         wcscpy(szBuffer, GetDirW(DriveIndex((char)*pInName)));
  630.         wcscat(szBuffer, &pInName[2]);
  631.         if(wcslen(szBuffer) > MAX_PATH)
  632.         szBuffer[MAX_PATH] = '\0';
  633.  
  634.         DoGetFullPathNameW(szBuffer, (sizeof(szLocalBufferW)/sizeof(WCHAR)), szLocalBufferW);
  635.     }
  636.     }
  637.     else {
  638.     /* no drive letter */
  639.     if (IsPathSep(pInName[1]) && IsPathSep(pInName[0])) {
  640.         /* UNC name */
  641.         wcscpy(szLocalBufferW, pInName);
  642.     }
  643.     else {
  644.         wcscpy(szBuffer, GetDefaultDirW());
  645.         if (IsPathSep(pInName[0])) {
  646.         /* absolute path */
  647.         szLocalBufferW[0] = szBuffer[0];
  648.         szLocalBufferW[1] = szBuffer[1];
  649.         wcscpy(&szLocalBufferW[2], pInName);
  650.         }
  651.         else {
  652.         /* relative path */
  653.         if (IsSpecialFileName(pInName)) {
  654.             return (WCHAR*)pInName;
  655.         }
  656.         else {
  657.             wcscat(szBuffer, pInName);
  658.             if (wcslen(szBuffer) > MAX_PATH)
  659.             szBuffer[MAX_PATH] = '\0';
  660.  
  661.             DoGetFullPathNameW(szBuffer, (sizeof(szLocalBufferW)/sizeof(WCHAR)), szLocalBufferW);
  662.         }
  663.         }
  664.     }
  665.     }
  666.     return szLocalBufferW;
  667. }
  668.  
  669. int VDir::SetCurrentDirectoryW(WCHAR *lpBuffer)
  670. {
  671.     WCHAR *pPtr;
  672.     int length, nRet = -1;
  673.  
  674.     pPtr = MapPathW(lpBuffer);
  675.     length = wcslen(pPtr);
  676.     if(length > 3 && IsPathSep(pPtr[length-1])) {
  677.     /* don't remove the trailing slash from 'x:\'  */
  678.     pPtr[length-1] = '\0';
  679.     }
  680.  
  681.     DWORD r = GetFileAttributesW(pPtr);
  682.     if ((r != 0xffffffff) && (r & FILE_ATTRIBUTE_DIRECTORY))
  683.     {
  684.     WCHAR wBuffer[(MAX_PATH+1)*2];
  685.     DoGetFullPathNameW(pPtr, (sizeof(wBuffer)/sizeof(WCHAR)), wBuffer);
  686.     SetDefaultDirW(wBuffer, DriveIndex((char)wBuffer[0]));
  687.     nRet = 0;
  688.     }
  689.  
  690.     return nRet;
  691. }
  692.  
  693. #endif    /* ___VDir_H___ */
  694.